package com.lazydong.apiforward.client.gui.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.lazydong.apiforward.client.framework.PageContainer;
import com.lazydong.apiforward.client.gui.constant.CommonConstant;
import com.lazydong.apiforward.client.gui.enums.PageEventEnum;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Slf4j
public class AppUpdateUtil {
    /**
     * 获取最新版本号
     *
     * @return Optional
     */
    public static Optional<String> getAppNewVersion() {
        HttpRequest get = HttpUtil.createGet(DomainUtil.serverDomain + CommonConstant.getAppNewVersion);
        get.setConnectionTimeout(2000);
        try (HttpResponse execute = get.execute()) {
            if (execute.getStatus() != 200) {
                // 服务器连接失败
                PageContainer.sendAsyncEvent(PageEventEnum.MAIN_PAGE_TIP, "服务器连接失败，请正确配置服务器地址");
                return Optional.empty();
            }
            String body = execute.body();
            if (hasNewVersion(body)) {
                return Optional.of(body);
            }
        } catch (Exception e) {
            PageContainer.sendAsyncEvent(PageEventEnum.MAIN_PAGE_TIP, "服务器连接失败，请正确配置服务器地址");
        }
        return Optional.empty();
    }

    public static boolean downUpdateExe(String newVersion) {
        log.info("开始下载新版本{}", newVersion);
        newVersion = newVersion.replace(".", "_");
        String lockFile = newVersion + "_update.lock";
        if (FileUtil.exist(CommonConstant.UPDATE_DIR + File.separator + lockFile)) {
            return true;
        }
        FileUtil.del(CommonConstant.UPDATE_DIR);
        String tempFile = CommonConstant.CURRENT_DIR + File.separator + "updateExeZip.zip";
        try (BufferedOutputStream outputStream = FileUtil.getOutputStream(tempFile)) {
            HttpUtil.download(DomainUtil.serverDomain + CommonConstant.downUpdateExe, outputStream, true);
            ZipUtil.unzip(tempFile, CommonConstant.UPDATE_DIR);
            FileUtil.touch(CommonConstant.UPDATE_DIR + File.separator + lockFile);
            FileUtil.del(tempFile);
            PageContainer.sendAsyncEvent(PageEventEnum.MAIN_PAGE_TIP, "检测到新版本 " + newVersion);
        } catch (IOException e) {
            FileUtil.del(tempFile);
            PageContainer.sendAsyncEvent(PageEventEnum.MAIN_PAGE_TIP, "辅助更新程序下载失败");
            return false;
        }
        return true;
    }

    public static void openUpdateExe() {
        String batDir = CommonConstant.CURRENT_DIR + File.separator + "bat";
        // 先写启动更新程序的脚本
        String startUpdateContent = JarResFileCopyUtil.loadResourceFile("bat", "startClientUpdate.bat");
        log.info("原始脚本{}", startUpdateContent);
        Map<String, String> param1 = new HashMap<>();
        param1.put("panFu", CommonConstant.UPDATE_DIR.substring(0, 2));
        param1.put("parentPath", CommonConstant.UPDATE_DIR);
        param1.put("clientUpdatePath", CommonConstant.UPDATE_EXE);
        startUpdateContent = StrUtil.format(startUpdateContent, param1);
        log.info("实际脚本{}", startUpdateContent);

        String startUpdatePath = batDir + File.separator + "startClientUpdate.bat";
        FileUtil.writeString(startUpdateContent, startUpdatePath, StandardCharsets.UTF_8);

        // 写任务计划脚本
        String launchProcessContent = JarResFileCopyUtil.loadResourceFile("bat", "launchProcess.bat");
        log.info("原始脚本{}", launchProcessContent);
        Map<String, String> param2 = new HashMap<>();
        param2.put("taskName", "startUpdateApiForward");
        param2.put("batPath", startUpdatePath);
        launchProcessContent = StrUtil.format(launchProcessContent, param2);
        log.info("实际脚本{}", startUpdateContent);
        String launchProcessPath = batDir + File.separator + "launchProcess.bat";
        FileUtil.writeString(launchProcessContent, launchProcessPath, StandardCharsets.UTF_8);
        try {
            log.info("执行更新脚本：脚本路径为 {}", launchProcessPath);
            ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", launchProcessPath);
            pb.directory(new File(CommonConstant.UPDATE_DIR));
            pb.start();
        } catch (IOException e) {
            log.error("启动失败", e);
            System.err.println("启动失败: " + e.getMessage());
        }
    }

    private static boolean hasNewVersion(String newVersion) {
        String[] newVersionArray = newVersion.split("\\.");
        String[] oldVersionArray = CommonConstant.APP_VERSION.split("\\.");
        int index = 0;
        while (true) {
            String newStr = getStrFromArray(newVersionArray, index);
            String oldStr = getStrFromArray(oldVersionArray, index);
            if (newStr == null && oldStr == null) {
                return false;
            }
            if (ifAMoreThanB(newStr, oldStr)) {
                return true;
            }
            index++;
        }
    }

    // 判断a是否比b大
    private static boolean ifAMoreThanB(String a, String b) {
        int a1 = Integer.parseInt(a);
        int b1 = Integer.parseInt(b);
        return a1 > b1;
    }

    private static String getStrFromArray(String[] strArray, int index) {
        if (strArray != null && strArray.length > index) {
            return strArray[index];
        }
        return null;
    }
}
